package qinyi365;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.apache.log4j.Logger;

public class MainClass {
	protected static final Logger logger = Logger.getLogger(MainClass.class);
	
	//static String host_name = "119.161.210.49";
	static String host_name = "localhost";
	static String database_b2c_name = "b2c";
	static String database_qymap_name = "qymap";
	static String username = "root";
	static String password = "qinyi365";
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		 while(true)
		{
			try {
				MainClass mainClass = new MainClass();
				mainClass.updateCoord();
			} catch (Exception e) {
				logger.info(e.getMessage());
				e.printStackTrace();
			}
		try {
			Thread.sleep(1000 * 60);
		} catch (InterruptedException e) {
			logger.info(e.getMessage());
			e.printStackTrace();
		}
		}
		 
	}

	public void updateCoord() {
		List<Map<String, String>> adds = new ArrayList<Map<String, String>>();//需要从百度上取经纬度的list
		List<Map<String, String>> notadds = new ArrayList<Map<String, String>>();//saparate表里有的不需要从百度取地址的list
		int updatecount = 0;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Connection conn = DriverManager.getConnection("jdbc:mysql://"
					+ host_name + "/" + database_b2c_name, username, password);
			conn.setAutoCommit(false);
			Statement stmt = conn.createStatement();

			String sql = "select fenbo_id,receiver_address,receiver_phone from qy_separate_data where status <> 1 and x = 0 and y = 0";
			ResultSet rs = stmt.executeQuery(sql);

				//查出所有需要分拨的数据
			int i=0;
			while (rs.next()) {
				System.out.println(i++);
				Map<String, String> map = new HashMap<String, String>();
				map.put("fenbo_id", rs.getString("fenbo_id"));
				String address = rs.getString("receiver_address");
				map.put("address", address);
				String receivephone1 = rs.getString("receiver_phone");
				map.put("receivephone", receivephone1);

				//取出电话号码后到saparate表里查询，看看是不是以前分拨过的数据
				List<String> phonelist = new ArrayList<String>();
				if (receivephone1 != null && receivephone1.length() > 0) {
					for (String str : receivephone1.split("，")) {
						phonelist.add(str);
					}
				}

				String xy = "";
				if (phonelist.size() > 0) {
					Statement sepStmt = conn.createStatement();
					String subSql = "";
					String subaddress = "";
					for (String phone : phonelist) {
						subSql = "select phone,address,x,y from qy_separate_record where phone = '" + phone.trim()
								+ "' and address = '" + address.trim().replaceAll("'", "") + "'";
						//System.out.println(subSql);
						ResultSet rssub = sepStmt.executeQuery(subSql);
						String x = "";
						String y = "";
						while (rssub.next()) {
							subaddress = rssub.getString("address");
							 x = rssub.getString("x");
						    y = rssub.getString("y");
						}
						
						
						if (!"".equals(x) && !"".equals(y) && !"0".equals(x) && !"0".equals(y)) {
							xy = x+","+y;
							break;
						}
					}
					sepStmt.close();
				}
				if (!"".equals(xy)) {//是分拨过的数据
					map.put("xy", xy);
					notadds.add(map);
				} else {//新数据
					adds.add(map);
				}
			}
			stmt.close();
			
			logger.info("需要处理" + (notadds.size() + adds.size()) +"条数据");
			if (notadds.size() > 0) {//以前分拨过的数据直接把从saparate表里取出来的网点ID更新到qy_import_data里
				Statement stmtUpdate = conn.createStatement();
				for (Map<String,String> map : notadds) {
					String xy = map.get("xy");
					String x = xy.split(",")[0];
					String y = xy.split(",")[1];
					sql = "update qy_separate_data set x = "+x+" , y = "+y+"  where fenbo_id = " + map.get("fenbo_id");
					stmtUpdate.execute(sql);
				}
				conn.commit();

			}
			conn.close();

		} catch (Exception e) {
			e.printStackTrace();
			logger.info(e.getMessage());
			
		}
		
		logger.info("有"+ adds.size() + "条数据需要重新获取坐标");
		if (adds.size() > 0) {//处理新数据
			int maxthreadcount = 5;//最大线程数
			List<List<Map<String, String>>> sublist = new ArrayList<List<Map<String, String>>>();
			List<Map<String, String>> list = new ArrayList<Map<String, String>>();
			for (int i = 0; i < adds.size(); i++) {
				if (i % (adds.size() / (maxthreadcount) + 1) == 0
						&& list.size() > 0) {
					sublist.add(list);
					list = new ArrayList<Map<String, String>>();
				}
				list.add(adds.get(i));
			}
			if (list.size() > 0)
				sublist.add(list);

			
			logger.info("开始获取坐标 .......");
			List<UpdataThread> utlist = new ArrayList<UpdataThread>();//线程list
			for (int i = 0; i < sublist.size(); i++) {
				Connection conn = null;
				try {
					conn = DriverManager.getConnection("jdbc:mysql://"
							+ host_name + "/" + database_b2c_name, username,
							password);
					conn.setAutoCommit(false);
				} catch (SQLException e) {
					e.printStackTrace();
					logger.info(e.getMessage());
					
				}

				//从百度地图api取坐标的线程
				UpdataThread ut = new UpdataThread(sublist.get(i), conn);
				utlist.add(ut);
				ut.start();
			}
			boolean notover = true;
			while (notover) {//等待所有线程结束
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
					logger.info(e.getMessage());
					
				}
				for (int i = 0; i < utlist.size(); i++) {
					if (!utlist.get(i).overflg)
						break;
					notover = false;
				}
			}
			logger.info("获取坐标结束 .......");
		}
		
		
		
		logger.info("开始分拨...............");
		Connection conn = null;
		String allexpressids = ",";
		try {
			conn = DriverManager.getConnection("jdbc:mysql://" + host_name
					+ "/" + database_qymap_name, username, password);
			conn.setAutoCommit(false);
			Statement stmt = conn.createStatement();
			String sql = "select express_id,express_coordinate from express_area order by express_id";
			//取出所有需要用到的网点信息
			ResultSet rs = stmt.executeQuery(sql);
			while (rs.next()) {
				String express_id = rs.getString("express_id");
				String coordinate = rs.getString("express_coordinate");
				String[] cs = coordinate.split(";");
				List<Point> plist = new ArrayList<Point>();
				for (String s : cs) {
					if (s != null && (s.indexOf(",") > 0)) {
						Point p = new Point(
								Double.valueOf(s.split(",")[0]), Double
										.valueOf(s.split(",")[1]));
						plist.add(p);

					}
				}
				if (plist.size() > 0) {
					double minx = getMinx(plist);
					double miny = getMiny(plist);
					double maxx = getMaxx(plist);
					double maxy = getMaxy(plist);
					Connection condata = null;
					condata = DriverManager.getConnection("jdbc:mysql://"
							+ host_name + "/" + database_b2c_name,
							username, password);
					condata.setAutoCommit(false);
					Statement stmtdata = condata.createStatement();
					//取出在这个网点多边形的外框范围内的数据
					String sqldata = "select fenbo_id,x,y,express_ids from qy_separate_data where x <= "
							+ maxx
							+ " and x >= "
							+ minx
							+ " and y <= "
							+ maxy
							+ " and y >= "
							+ miny
							+ " and status <> 1 and x <> 0 and y <> 0";
					ResultSet rsdata = stmtdata.executeQuery(sqldata);
					Statement stmtdataupdate = condata.createStatement();
					while (rsdata.next()) {
						String fenbo_id = rsdata.getString("fenbo_id");
						double x = rsdata.getDouble("x");
						double y = rsdata.getDouble("y");
						String expressids = rsdata.getString("express_ids");
						//判断这条地址是否在网点的多边形里
						if (isPointInPolygon(x, y, plist)) {
							if(expressids == null || "".equals(expressids))
								expressids = ",";
							expressids += express_id + ",";
							stmtdataupdate
									.execute("update qy_separate_data set express_ids = '"
											+ expressids + "'"
											+ " where fenbo_id = "
											+ fenbo_id);
						}
					}
					stmtdataupdate.close();
					condata.commit();
					condata.close();
				}
				
				allexpressids += express_id + ",";
			}
			stmt.close();
			conn.close();
			//fenbo

		} catch (SQLException e) {
			e.printStackTrace();
			logger.info(e.getMessage());
			
		}
		
		
		Map<String, Integer> sets = new HashMap<String, Integer>();
		//List<String> allids = new ArrayList<String>();
		
		try {
			conn = DriverManager.getConnection("jdbc:mysql://" + host_name
					+ "/" + database_b2c_name, username, password);
			conn.setAutoCommit(false);
			Statement stmt = conn.createStatement();
			String sql = "select express_id,dealing from qy_set_separate order by dealing desc";
			
			// 取出所有需要用到的网点信息
			ResultSet rs = stmt.executeQuery(sql);
			while (rs.next()) {
				String express_id = rs.getString("express_id");
				sets.put(express_id, rs.getInt("dealing"));
			//	allids.add(express_id);
			}
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		List<String> fenboids = new ArrayList<String>();
		List<String> express_idss = new ArrayList<String>();
		String sql ="";
		try {
			conn = DriverManager.getConnection("jdbc:mysql://" + host_name
					+ "/" + database_b2c_name, username, password);
			conn.setAutoCommit(false);
			Statement stmt = conn.createStatement();
			sql= "select fenbo_id,express_ids from qy_separate_data where status <> 1 and express_ids is not null and express_ids !=''";//where ecress_ids = '"+allexpressids+"'";
			
			// 取出所有需要用到的网点信息
			ResultSet rs = stmt.executeQuery(sql);
			while (rs.next()) {
				fenboids.add(rs.getString("fenbo_id"));
				express_idss.add(rs.getString("express_ids"));
			}
			Map<String,String>  map = getfenboFromallIds(sets,fenboids,express_idss);
			
			Iterator<String> strs = map.keySet().iterator();
			while(strs.hasNext())
			{
				updatecount++;
				System.out.println(updatecount);
				String key = strs.next();
				int motostatus = getStatusbyId(key);
				sql = "update qy_separate_data set status = 1, express_id = "+map.get(key)+" where fenbo_id = "+key+"";
				stmt.execute(sql);

				if(motostatus != 5)
				{
					sql = "select bill_code,RECEIVER_NAME,RECEIVER_ADDRESS, RECEIVER_PHONE,PROVINCE,CITY,x,y from qy_separate_data where fenbo_id = "+key;
					 rs = stmt.executeQuery(sql);
					Connection conn1 = DriverManager.getConnection("jdbc:mysql://" + host_name
								+ "/" + database_b2c_name, username, password);
					Statement stmtsub = conn1.createStatement();
					while (rs.next()) {
						String bill_code = rs.getString("bill_code");
						String strname = rs.getString("RECEIVER_NAME");
						String straddress = rs.getString("RECEIVER_ADDRESS");
						String strphone = rs.getString("RECEIVER_PHONE");
						String strprovince = rs.getString("PROVINCE");
						String strcity = rs.getString("CITY");
						String strx = rs.getString("x");
						String stry = rs.getString("y");
						sql = "INSERT INTO qy_import_data( GOODS_ID, RECEIVER_NAME, RECEIVER_ADDRESS , " +
						"RECEIVER_PHONE1 , RECEIVER_PHONE2 , RECEIVER_MAIL , RECEIVER_PAYMENT , RECEIVER_FREIGHT , " +
						"DELIVERY_DATE , DELIVERY_TIME , ADDDATE, NETWORK_ID  , IS_SELECTED  , PROVINCE  , CITY  ," +
						" DISTRICT  , google_x  , google_y,x,y) VALUES( '"+bill_code+"'  , '"+strname+"'  , '"+straddress+"'   , '"+strphone+"' , '' " +
						", '' , ''  , ''  , '' , ''  , now()  , -1  , 0  , '"+strprovince+"'  , '"+strcity+"'  , ''  , "+strx+"  ," +
						stry+",0,0)";
						stmtsub.execute(sql);
					}
					stmtsub.close();
					conn1.close();
				}
			}
			
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			logger.info(sql);
			e.printStackTrace();
		}
		
		
		
		try
		{
			Class.forName("com.mysql.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://"
					+ host_name + "/" + database_b2c_name, username, password);
			con.setAutoCommit(false);
			Statement stmt = con.createStatement();
			Statement stmtupdate = con.createStatement();
			sql = "select fenbo_id,bill_code,RECEIVER_NAME,RECEIVER_ADDRESS, RECEIVER_PHONE,PROVINCE,CITY,x,y  from qy_separate_data  where status <> 1 and status <> 5";
			ResultSet sysrs = stmt.executeQuery(sql);
		   //查出需要分拨失败且没有同步的数据
			while (sysrs.next()) {
				String fenbo_id = sysrs.getString("fenbo_id");
				String bill_code = sysrs.getString("bill_code");
				String strname = sysrs.getString("RECEIVER_NAME");
				String straddress = sysrs.getString("RECEIVER_ADDRESS");
				String strphone = sysrs.getString("RECEIVER_PHONE");
				String strprovince = sysrs.getString("PROVINCE");
				String strcity = sysrs.getString("CITY");
				String strx = sysrs.getString("x");
				String stry = sysrs.getString("y");
				if(strx == null || strx.equals("null"))
					strx = "0";
				if(stry == null || stry.equals("null"))
					stry = "0";
				sql = "INSERT INTO qy_import_data( GOODS_ID, RECEIVER_NAME, RECEIVER_ADDRESS , " +
				"RECEIVER_PHONE1 , RECEIVER_PHONE2 , RECEIVER_MAIL , RECEIVER_PAYMENT , RECEIVER_FREIGHT , " +
				"DELIVERY_DATE , DELIVERY_TIME , ADDDATE, NETWORK_ID  , IS_SELECTED  , PROVINCE  , CITY  ," +
				" DISTRICT  , google_x  , google_y,x,y) VALUES( '"+bill_code+"'  , '"+strname+"'  , '"+straddress+"'   , '"+strphone+"' , '' " +
				", '' , ''  , ''  , '' , ''  , now()  , -1  , 0  , '"+strprovince+"'  , '"+strcity+"'  , ''  , "+strx+"  ," +
				stry+",0,0)";
				stmtupdate.execute(sql);
				sql = "update qy_separate_data set status = 5 where fenbo_id = "+fenbo_id+"";
				stmtupdate.execute(sql);
			}
			stmt.close();
			stmtupdate.close();
			con.close();
		}
		catch(Exception e)
		{
			logger.info(sql);
			logger.info(e.getMessage());
			e.printStackTrace();
		}
		logger.info("分拨结束，成功分拨" + updatecount +"条数据");
	}

	private int getStatusbyId(String fenbo_id)
	{
		String sql = "select status from qy_separate_data where fenbo_id = "+fenbo_id;
		int status = 0;
		try
		{
			Class.forName("com.mysql.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://"
					+ host_name + "/" + database_b2c_name, username, password);
			con.setAutoCommit(false);
			Statement stmt = con.createStatement();
			ResultSet sysrs = stmt.executeQuery(sql);
			
			while (sysrs.next()) {
				status = sysrs.getInt("status");
			}
			stmt.close();
			con.close();
		}
		catch(Exception e)
		{
			logger.info(sql);
			logger.info(e.getMessage());
			e.printStackTrace();
		}
		return status;
	}
	private Map<String,String> getfenboFromallIds(Map<String,Integer> map,List<String> ids,List<String> express_idss)
	{
		Map<String,String> returnmap= new HashMap<String,String>();
		for(int i = 0;i < ids.size();i++)
		{
			String exressids = express_idss.get(i);
			String strs[] = exressids.split(",");
			Map<String,Integer> submap= new HashMap<String,Integer>();
			for(String str : strs)
			{
				if(!str.equals(""))
				{
					if(map.containsKey(str))
						submap.put(str, map.get(str));
				}
			}
			TreeMap<Integer,String>   treemap = convertScale(submap);
			
			 Set<Integer> set=treemap.keySet();
			  Iterator<Integer>  iter=set.iterator();
			int s=  (int) (Math.random()* 100);
			  while(iter.hasNext()){
				  Integer key=iter.next();
				  if(s < key)
				  {
					  returnmap.put(ids.get(i), treemap.get(key)); 
					  break;
				  }
			  }
			  
		}
		return returnmap;
	}
	private TreeMap<Integer,String>  convertScale(Map<String,Integer> map)
	{
		Iterator<String> strs = map.keySet().iterator();
		double all = 0;
		while(strs.hasNext())
		{
			String key = strs.next();
			all += map.get(key);
		}
		TreeMap<Integer,String> maps = new TreeMap<Integer,String>();
		int count = 0;
		Iterator<String> strsnew = map.keySet().iterator();
		int size = 0;
		while(strsnew.hasNext())
		{
			size++;
			String key = strsnew.next();
			int value = (int) (map.get(key)/all * 100);
			count+=value;
			if(size == map.size())
			{
				if(count < 100)
					count = 100;
			}
			maps.put(Integer.valueOf(count), key);
		}
		return maps;
	}
	private double getMinx(List<Point> plist) {
		double maxdouble = Double.MAX_VALUE;
		for (Point p : plist) {
			if (p.lng < maxdouble) {
				maxdouble = p.lng;
			}
		}
		return maxdouble;
	}

	private double getMiny(List<Point> plist) {
		double maxdouble = Double.MAX_VALUE;
		for (Point p : plist) {
			if (p.lat < maxdouble) {
				maxdouble = p.lat;
			}
		}
		return maxdouble;
	}

	private double getMaxx(List<Point> plist) {
		double mindouble = 0;
		for (Point p : plist) {
			if (p.lng > mindouble) {
				mindouble = p.lng;
			}
		}
		return mindouble;
	}

	private double getMaxy(List<Point> plist) {
		double mindouble = 0;
		for (Point p : plist) {
			if (p.lat > mindouble) {
				mindouble = p.lat;
			}
		}
		return mindouble;
	}

	public boolean isPointInPolygon(double px, double py, List<Point> plist) {
		boolean isInside = false;
		double ESP = 1e-9;
		int count = 0;
		double linePoint1x;
		double linePoint1y;
		double linePoint2x = 180;
		double linePoint2y;

		linePoint1x = px;
		linePoint1y = py;
		linePoint2y = py;

		for (int i = 0; i < plist.size() - 1; i++) {
			double cx1 = plist.get(i).lng;
			double cy1 = plist.get(i).lat;
			double cx2 = plist.get(i + 1).lng;
			double cy2 = plist.get(i + 1).lat;
			if (isPointOnLine(px, py, cx1, cy1, cx2, cy2)) {
				return true;
			}
			if (Math.abs(cy2 - cy1) < ESP) {
				continue;
			}

			if (isPointOnLine(cx1, cy1, linePoint1x, linePoint1y, linePoint2x,
					linePoint2y)) {
				if (cy1 > cy2)
					count++;
			} else if (isPointOnLine(cx2, cy2, linePoint1x, linePoint1y,
					linePoint2x, linePoint2y)) {
				if (cy2 > cy1)
					count++;
			} else if (isIntersect(cx1, cy1, cx2, cy2, linePoint1x,
					linePoint1y, linePoint2x, linePoint2y)) {
				count++;
			}
		}
		if (count % 2 == 1) {
			isInside = true;
		}

		return isInside;
	}

	public double Multiply(double px0, double py0, double px1, double py1,
			double px2, double py2) {
		return ((px1 - px0) * (py2 - py0) - (px2 - px0) * (py1 - py0));
	}

	public boolean isPointOnLine(double px0, double py0, double px1,
			double py1, double px2, double py2) {
		boolean flag = false;
		double ESP = 1e-9;
		if ((Math.abs(Multiply(px0, py0, px1, py1, px2, py2)) < ESP)
				&& ((px0 - px1) * (px0 - px2) <= 0)
				&& ((py0 - py1) * (py0 - py2) <= 0)) {
			flag = true;
		}
		return flag;
	}

	public boolean isIntersect(double px1, double py1, double px2, double py2,
			double px3, double py3, double px4, double py4) {
		boolean flag = false;
		double d = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3);
		if (d != 0) {
			double r = ((py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3))
					/ d;
			double s = ((py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1))
					/ d;
			if ((r >= 0) && (r <= 1) && (s >= 0) && (s <= 1)) {
				flag = true;
			}
		}
		return flag;
	}
}
